﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Newtonsoft.Json.Linq;

namespace SimpleGp
{
    /// <summary>
    /// MainUserControl.xaml 的交互逻辑
    /// </summary>
    public partial class MainUserControl : UserControl
    {
        private System.Threading.SynchronizationContext synContent = null;
        private int TotalGpCount = 100;
        private bool IsResponsing = false;
        private Stopwatch ShowWatch = new Stopwatch();
        private int GpIndex = 0;
        private bool IsStop = false;

        private Thread m_backThread;
        public MainUserControl()
        {
            InitializeComponent();
            synContent = System.Threading.SynchronizationContext.Current;
            ShowWatch.Start();
            m_backThread = new System.Threading.Thread(() =>
            {
                Stopwatch stopwatch = new Stopwatch();
                while (this != null && !IsStop)
                {
                    try
                    {
                        var gps = GetValidGps();
                        if (gps == null || gps.Count <= 0)
                            continue;

                        stopwatch.Restart();
                        FlashData(gps[GpIndex]);

                        while (stopwatch.ElapsedMilliseconds < 1000)
                        {
                            System.Threading.Thread.Sleep(500);
                        }
                        GpIndex++;
                        if (GpIndex >= gps.Count)
                            GpIndex = 0;
                    }
                    catch (Exception ex)
                    {

                    }

                }

            });
            m_backThread.IsBackground = true;
            m_backThread.Start();
        }

        /// <summary>
        /// 实时刷新数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void FlashData(string code)
        {
            string url = GetUrlForSingleRealTimeData(code);

            if (IsResponsing)
                return;
            try
            {
                IsResponsing = true;

                //var ents = GetGPData(url, 3).Result;
                var ent = GetGpDataForSingle(url, 5).Result;

                //for (int i = 0; i < ents.Count; i++)
                //{
                //    if (!gps.Contains(ents[i].Code))
                //    {
                //        ents.RemoveAt(i--);
                //    }
                //}
                //GpIndex++;
                //if (GpIndex >= ents.Count)
                //    GpIndex = 0;
                //if (ShowWatch.ElapsedMilliseconds > 2000)
                //{
                //    GpIndex++;
                //    if (GpIndex >= ents.Count)
                //        GpIndex = 0;
                //    ShowWatch.Restart();
                //}
                Color color = Colors.White;
                if(ent.MarkUp >= 0)
                {
                    color = Colors.Red;
                }
                else
                {
                    color = Colors.Green;
                }
                Name.Dispatcher.Invoke(new Action(() =>
                {
                    Name.Text = ent.Name;
                    Name.Foreground = new SolidColorBrush(color);
                }));
                MarkUp.Dispatcher.Invoke(new Action(() =>
                {
                    MarkUp.Text = ent.MarkUp.ToString();
                    MarkUp.Foreground = new SolidColorBrush(color);
                }));
                //synContent.Post(FlashViewData, ents);

            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
                IsResponsing = false;
            }
            IsResponsing = false;
        }
        private void FlashViewData(object obj)
        {
            var list = obj as List<GpEntity>;
            Name.Text = list[0].Name;
            MarkUp.Text = list[0].MarkUp.ToString();
        }
        /// <summary>
        /// 获取实时数据
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private async Task<List<GpEntity>> GetGPData(string url, int timeOutMs = 60)
        {
            List<GpEntity> ents = new List<GpEntity>();
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.Timeout = new TimeSpan(0, 0, timeOutMs);
                    HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false);
                    if (response.IsSuccessStatusCode)
                    {
                        response.EnsureSuccessStatusCode();
                        string htmlContent = response.Content.ReadAsStringAsync().Result;
                        if (!string.IsNullOrEmpty(htmlContent))
                        {
                            JObject jobject = JObject.Parse(htmlContent);
                            var childrens = jobject["data"]["diff"].Children();
                            string totalStr = jobject["data"]["total"].ToString();
                            if (!string.IsNullOrEmpty(totalStr))
                            {
                                int.TryParse(totalStr, out TotalGpCount);
                            }

                            foreach (var item in childrens)
                            {
                                GpEntity ent = new GpEntity();
                                ent.Code = item["f12"].ToString();
                                ent.Name = item["f14"].ToString();
                                ent.MarkUp = float.TryParse(item["f3"].ToString(), out float curMarkup) ? curMarkup : 0.0f;
                                ents.Add(ent);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {

            }

            return ents;
        }

        private async Task<GpEntity> GetGpDataForSingle(string url, int timeOutMs = 60)
        {
            try
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; ;
                using (HttpClient client = new HttpClient())
                {
                    client.Timeout = new TimeSpan(0, 0, timeOutMs);
                    HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false);
                    if (response.IsSuccessStatusCode)
                    {
                        response.EnsureSuccessStatusCode();
                        string htmlContent = response.Content.ReadAsStringAsync().Result;
                        if (!string.IsNullOrEmpty(htmlContent))
                        {
                            JObject jobject = JObject.Parse(htmlContent);
                            var data = jobject["data"];

                            GpEntity ent = new GpEntity();
                            ent.Code = data["f57"].ToString();
                            ent.Name = data["f58"].ToString();
                            ent.MarkUp = float.TryParse(data["f170"].ToString(), out float curMarkup) ? curMarkup : 0.0f;

                            return ent;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                
            }
             return null;
        }
        #region 私有方法
        private string GetUrl()
        {
            return $"http://74.push2.eastmoney.com/api/qt/clist/get?&pn=1&pz={TotalGpCount}&po=1&np=1&fltt=2&invt=2&wbp2u=|0|0|0|web&fid=f22&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048&fields=f2,f3,f12,f14,f20,f22,f11";

        }
        /// <summary>
        /// 获取指定股票实时数据
        /// </summary>
        /// <returns></returns>
        private string GetUrlForSingleRealTimeData(string code)
        {
            int typeId = 0;
            if (code.StartsWith("00"))
            {
                typeId = 0;
            }
            else if (code.StartsWith("60"))
            {
                typeId = 1;
            }
            else
            {
                return "";
            }
            return $"https://15.push2.eastmoney.com/api/qt/stock/get?fltt=2&invt=2&volt=2&fields=f43,f57,f58,f169,f170,f46,f44,f45&secid={typeId}.{code}";

        }

        private bool m_IsFirst = true;
        private List<string> m_ListGp = new List<string>();
        private DateTime m_LastModifyTime;
        private int m_MsgNum = 0;
        private List<string> GetValidGps()
        {
            try
            {
                string path = this.GetType().Assembly.Location.Replace("SimpleGp.dll", "LockFile.txt");
                if (File.Exists(path))
                {
                    if (m_IsFirst || File.GetLastWriteTime(path) != m_LastModifyTime)
                    {
                        m_IsFirst = false;
                        m_LastModifyTime = File.GetLastWriteTime(path);
                        var str = File.ReadAllText(path);
                        if (!string.IsNullOrEmpty(str))
                        {
                            var strs = str.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            m_ListGp = strs;

                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if(m_MsgNum < 2)
                {
                    MessageBox.Show(ex.Message);
                    m_MsgNum++;
                }
            }


            return m_ListGp;
        }
        #endregion

        private Brush ControlBrush = null;
        private void MyControl_MouseEnter(object sender, MouseEventArgs e)
        {
            ControlBrush = MyControl.Background;
            MyControl.Background = new SolidColorBrush(Color.FromRgb(175, 175, 175));
        }

        private void MyControl_MouseLeave(object sender, MouseEventArgs e)
        {
            MyControl.Background = ControlBrush;
        }

        private void MyControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show("打开窗口");
        }

        private void FlashBtn_Click(object sender, RoutedEventArgs e)
        {
            IsStop = true;
            while (this != null)
            {
                if(m_backThread.ThreadState == System.Threading.ThreadState.Stopped)
                {
                    IsStop = false;
                    m_backThread.Start();
                }
            }
        }
    }

    public class GpEntity
    {
        public string Code { get; set; }
        public string Name { get; set; }
        public float MarkUp { get; set; }
    }
}
